import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, confusion_matrix
from collections import Counter
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix, precision_recall_curve, roc_curve, auc

# 读取Excel文件
def load_data(file_path):
    # 使用pandas读取Excel文件
    data = pd.read_excel(file_path, sheet_name='Sheet1', engine='openpyxl')
    
    # 将所有列名转换为字符串
    data.columns = data.columns.astype(str)
    
    df = data.iloc[1:801, 1:207]  # 根据实际情况调整
    return df

# 训练和评估SVM模型
def train_evaluate_svm(df):
    # 假设FT列为分类的真实值
    X = df.drop('label', axis=1)  # 特征数据
    y = df['label']               # 标签数据

    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=26)

    # 创建SVM分类器
    svm_classifier = SVC(kernel='linear', class_weight={0:1, 1:20})  # 可以调整kernel参数，这里选择增大假阳性惩罚

    # 训练模型
    svm_classifier.fit(X_train, y_train)

    # 预测测试集
    y_pred = svm_classifier.predict(X_test)

    # 计算准确率
    accuracy = accuracy_score(y_test, y_pred)
    print(f"Accuracy: {accuracy}")

    # 计算混淆矩阵
    cm = confusion_matrix(y_test, y_pred)
    print(f"Confusion Matrix:\n{cm}")

    # 绘制混淆矩阵
    plt.figure(figsize=(8, 6))
    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=y_test.unique(), yticklabels=y_test.unique())
    plt.xlabel('Predicted labels')
    plt.ylabel('True labels')
    plt.title('Confusion Matrix')
    plt.show()

    # 计算ROC曲线所需的阈值和分数
    y_scores = svm_classifier.decision_function(X_test)
    fpr, tpr, _ = roc_curve(y_test, y_scores)
    roc_auc = auc(fpr, tpr)

    # 绘制ROC曲线
    plt.figure(figsize=(8, 6))
    plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')
    plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title('Receiver Operating Characteristic')
    plt.legend(loc="lower right")
    plt.show()

    # 计算PR曲线
    precision, recall, _ = precision_recall_curve(y_test, y_scores)
    plt.figure(figsize=(8, 6))
    plt.plot(recall, precision, color='darkorange', lw=2)
    plt.xlabel('Recall')
    plt.ylabel('Precision')
    plt.title('Precision-Recall Curve')
    plt.show()

    return svm_classifier, y_pred, accuracy, cm

def predict_and_append_labels(df, model):
    # 确保所有列名都是字符串类型
    df.columns = df.columns.astype(str)
    # 使用模型进行预测
    predictions = model.predict(df)
    
    # 将预测结果作为新列添加到数据框中
    df['predicted_label'] = predictions

    return df

# 主程序
if __name__ == "__main__":
    file_path = 'train_data.xlsx'  # 替换为你的Excel文件路径
    df = load_data(file_path)
    model, predictions, accuracy, confusion_matrix = train_evaluate_svm(df)
    # 假设你有一个用于预测的DataFrame，这里我们使用训练数据作为示例
    #df2 = pd.read_excel('data.xlsx')
    #df_predictions = predict_and_append_labels(df2, model)  # 使用模型进行预测并添加标签

    # 如果需要，可以将更新后的DataFrame保存到新的Excel文件
    #df_predictions.to_excel('prediction_data.xlsx', index=True, engine='openpyxl')